package me.ilich.piet.interpreter;

import me.ilich.piet.interpreter.commands.AddCommand;
import me.ilich.piet.interpreter.commands.Command;
import me.ilich.piet.interpreter.commands.DivideCommand;
import me.ilich.piet.interpreter.commands.DuplicateCommand;
import me.ilich.piet.interpreter.commands.GreaterCommand;
import me.ilich.piet.interpreter.commands.InCharCommand;
import me.ilich.piet.interpreter.commands.InNumberCommand;
import me.ilich.piet.interpreter.commands.ModCommand;
import me.ilich.piet.interpreter.commands.MultiplyCommand;
import me.ilich.piet.interpreter.commands.NotCommand;
import me.ilich.piet.interpreter.commands.OutCharCommand;
import me.ilich.piet.interpreter.commands.OutNumberCommand;
import me.ilich.piet.interpreter.commands.PointerCommand;
import me.ilich.piet.interpreter.commands.PopCommand;
import me.ilich.piet.interpreter.commands.PushCommand;
import me.ilich.piet.interpreter.commands.RollCommand;
import me.ilich.piet.interpreter.commands.SubtractCommand;
import me.ilich.piet.interpreter.commands.SwitchCommand;
import me.ilich.piet.interpreter.elements.Block;

public final class CommandsFactory {
	
	private CommandsFactory(){}
	
	public static final Command instanceCommand(Block source, Block destination){
		if(source==null) throw new NullPointerException("source");
		if(destination==null) throw new NullPointerException("destination");
		Command command = null;
		final int brigthnessDif = ColoursCompare.brightnessDif(source, destination);
		final int colorDif = ColoursCompare.brightnessDif(source, destination);
		final int dif = brigthnessDif + colorDif * 3;
		switch (dif) {
		case 1:
			command = new PushCommand(source.getSize());
			break;
		case 2:
			command = new PopCommand();
			break;
		case 3:
			command = new AddCommand();
			break;
		case 4:
			command = new SubtractCommand();
			break;			
		case 5:
			command = new MultiplyCommand();
			break;
		case 6:
			command = new DivideCommand();
			break;
		case 7:
			command = new ModCommand();
			break;
		case 8:
			command = new NotCommand();
			break;
		case 9:
			command = new GreaterCommand();
			break;
		case 10:
			command = new PointerCommand();
			break;
		case 11:
			command = new SwitchCommand();
			break;
		case 12:
			command = new DuplicateCommand();
			break;
		case 13:
			command = new RollCommand();
			break;
		case 14:
			command = new InNumberCommand();
			break;
		case 15:
			command = new InCharCommand();
			break;
		case 16:
			command = new OutNumberCommand();
			break;
		case 17:
			command = new OutCharCommand();
			break;
		default:
			throw new RuntimeException("invalid block diff " + dif);
		}
		return command;
	}

}
